package com.mainbo.modular.excel.impl;

import cn.hutool.core.io.resource.ClassPathResource;
import cn.stylefeng.roses.core.util.HttpContext;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.mainbo.core.orm.MapperContainer;
import com.mainbo.core.orm.Table;
import com.mainbo.core.shiro.SessionKey;
import com.mainbo.core.shiro.ShiroKit;
import com.mainbo.core.util.ExcelUtils;
import com.mainbo.core.util.ExcelUtils.ExcelType;
import com.mainbo.core.util.Reflections;
import com.mainbo.modular.excel.BatchClassService;
import com.mainbo.modular.excel.ExcelBatchService;
import com.mainbo.modular.jms.JmsService;
import com.mainbo.modular.jms.MessageTypes;
import com.mainbo.modular.jms.model.ClassInfoMessage;
import com.mainbo.modular.system.dao.PtAreaMapper;
import com.mainbo.modular.system.dao.PtClassMapper;
import com.mainbo.modular.system.dao.PtOrgMapper;
import com.mainbo.modular.system.model.*;
import com.mainbo.modular.system.model.meta.MetaUtils;
import com.mainbo.modular.system.model.meta.vo.Meta;
import com.mainbo.modular.system.service.IPtClassService;
import com.mainbo.modular.system.service.IPtUserRoleService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author moshang
 * @date 2020-03-07
 **/
@Service
public class BatchClassServiceImpl extends ExcelBatchService implements BatchClassService {
    private static final Logger logger = LoggerFactory.getLogger(BatchClassServiceImpl.class);
    @Resource
    private PtOrgMapper orgMapper;
    @Resource
    private PtAreaMapper areaMapper;
    @Resource
    private IPtUserRoleService ptUserRoleService;
    @Resource
    private IPtClassService classService;
    @Resource
    private JmsService jmsService;
    @Resource
    private PtClassMapper classMapper;
    /**
     * 用户模板头部所在行
     */
    private final Integer headline = 3;



    enum ExcelHeader implements ExcelTitle {
        PERIOD(false, 4, "级届"), GRADE(false, 16, "年级"), CLASSNAME(true, 32, "班级名称", "班级"), TEACHER(false, 32, "班主任", "班主任姓名", "老师姓名"), SUBJECTTYPE(false, 32,
                "文理科"), CLASSTYPE(false, 32, "班级类型");

        private String[] mapNames;

        private boolean required = false;

        private Integer size = null;

        private ExcelHeader(String... header) {
            this.mapNames = header;
        }

        private ExcelHeader(boolean required, String... header) {
            this.mapNames = header;
            this.required = required;
        }

        private ExcelHeader(Integer size, String... header) {
            this.mapNames = header;
            this.size = size;
        }

        private ExcelHeader(boolean required, Integer size, String... header) {
            this.mapNames = header;
            this.required = required;
            this.size = size;
        }

        @Override
        public List<String> getMapNames() {
            return Arrays.asList(mapNames);
        }

        @Override
        public boolean isRequired() {
            return required;
        }

        @Override
        public int length() {
            return size;
        }
    }
    @Override
    public void downloadBatchClassTemplate(String orgId, HttpServletResponse response, Integer schoolYear) throws IOException {
        Workbook workbook = null;

        String fileName = "批量导入" + schoolYear + "学年班级";
        String filepath = "";
        filepath = "/registertemplate/batchtemplate_class.xls";
        ClassPathResource resource = new ClassPathResource(filepath);
        InputStream inputStream = resource.getStream();
        workbook = ExcelUtils.createWorkBook(inputStream,ExcelType.EXL_2003);
        if (workbook == null) {
            returnErrMsg(filepath, response);
            return;
        }
        Sheet sheet = workbook.getSheet("Sheet");
        PtOrg org = orgMapper.selectById(orgId);
        String orgStr = "学校：" + org.getName();
        PtArea area1 = areaMapper.selectById(org.getAreaId());
        if (area1.getPid().intValue() != 0) {
            PtArea area2 = areaMapper.selectById(area1.getPid());
            orgStr = "省(市)：" + area2.getAreaName() + "     区(县)：" + area1.getAreaName() + "     " + orgStr;
        } else {
            orgStr = "区(县)：" + area1.getAreaName() + "     " + orgStr;
        }
        sheet.getRow(2).getCell(0).setCellValue(orgStr);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(TITLE_PARAMS, new HashSet<ExcelTitle>());
        Map<ExcelTitle, Column> headers = parseExcelHeader(sheet, params);
        initSheetTeplate(workbook, sheet, org, headers);
        try {
            if (workbook != null) {
                String ext = filepath.substring(filepath.lastIndexOf("."));
                response.reset();
                response.setContentType("application/x-msdownload");
                response.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes("gb2312"), "ISO-8859-1") + ext);
                workbook.write(response.getOutputStream());
            } else {
                response.getWriter().write("模板文件不存在！");
            }
        } catch (Exception e) {
            logger.error("", e);

        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    logger.error("close failed", e);
                }
            }
        }
    }
    private void returnErrMsg(String path, HttpServletResponse response) {
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        StringBuilder rb = new StringBuilder(path).append(" 不存在!");
        try {
            response.getWriter().write(rb.toString());
        } catch (IOException e) {
            logger.error("", e);
        }
    }
    /**
     * 初始化模板
     *
     */
    private void initSheetTeplate(Workbook workbook, Sheet sheet, PtOrg org, Map<ExcelTitle, Column> headers) {
        Column cn = null;
        List<String> periodList = createPeriodList();// 级届集合
        String[] periodArray = new String[10];
        List<Meta> gradeMetas = getAllgradeMetaList(org);
        String[] gradeNameArray = new String[gradeMetas.size()];
        for (int i = 0; i < gradeMetas.size(); i++) {
            Meta meta = gradeMetas.get(i);
            gradeNameArray[i] = meta.getName();
        }
        Integer gradeClumnIndex = null;
        if ((cn = headers.get(ExcelHeader.GRADE)) != null) {
            gradeClumnIndex = cn.getIndex();
        }
        Integer periodClumnIndex = null;
        if ((cn = headers.get(ExcelHeader.PERIOD)) != null) {
            periodClumnIndex = cn.getIndex();
        }
        if (periodClumnIndex != null && gradeClumnIndex != null) {
            DataValidation setDataValidationName1 = ExcelUtils.createDataValidation(sheet, periodList.toArray(periodArray), headline + 1, 300, periodClumnIndex,
                    periodClumnIndex);
            sheet.addValidationData(setDataValidationName1);
            DataValidation setDataValidationName2 = ExcelUtils.createDataValidation(sheet, gradeNameArray, headline + 1, 300, gradeClumnIndex, gradeClumnIndex);
            sheet.addValidationData(setDataValidationName2);
        }
        if ((cn = headers.get(ExcelHeader.TEACHER)) != null) { // 如果需要导入班主任
            Map<String, String> teacherMap = getTeacherMap(org.getId());
            String[] teacherNameArray = new String[teacherMap.keySet().size()];
            Integer teacherColumnIndex = cn.getIndex();
            DataValidation setDataValidationName3 = ExcelUtils.createDataValidation(sheet, teacherMap.keySet().toArray(teacherNameArray), headline + 1, 300,
                    teacherColumnIndex, teacherColumnIndex);
            sheet.addValidationData(setDataValidationName3);
        }
        if ((cn = headers.get(ExcelHeader.CLASSTYPE)) != null) { // 如果需要导入班级类型
            Map<String, Integer> classTypeMap = getMetaMap("class_type");
            String[] classTypeArray = new String[classTypeMap.keySet().size()];
            Integer chassTypeColumnIndex = cn.getIndex();
            DataValidation setDataValidationName4 = ExcelUtils.createDataValidation(sheet, classTypeMap.keySet().toArray(classTypeArray), headline + 1, 300,
                    chassTypeColumnIndex, chassTypeColumnIndex);
            sheet.addValidationData(setDataValidationName4);
        }
        if ((cn = headers.get(ExcelHeader.SUBJECTTYPE)) != null) { // 如果需要导入文理科
            Map<String, Integer> subjectTypeMap = getMetaMap("department_system");
            String[] subjectTypeArray = new String[subjectTypeMap.keySet().size()];
            Integer subjectTypeColumnIndex = cn.getIndex();
            DataValidation setDataValidationName5 = ExcelUtils.createDataValidation(sheet, subjectTypeMap.keySet().toArray(subjectTypeArray), headline + 1, 300,
                    subjectTypeColumnIndex, subjectTypeColumnIndex);
            sheet.addValidationData(setDataValidationName5);
        }
    }

    /**
     * 获取班级类型map
     *
     */
    private Map<String, Integer> getMetaMap(String code) {
        List<Meta> metaList = MetaUtils.listMeta(code);
        Map<String, Integer> metaMap = new HashMap<String, Integer>();
        for (Meta m : metaList) {
            metaMap.put(m.getName(), m.getId());
        }
        return metaMap;
    }
    /**
     * 生成级届集合
     *
     */
    private List<String> createPeriodList() {
        int count = 10;
        List<String> periodList = new ArrayList<String>();
        Integer courrentPeriod = Integer.valueOf(new SimpleDateFormat("yyyy").format(new Date()));
        for (int i = 0; i < count; i++) {
            periodList.add(String.valueOf(courrentPeriod));
            courrentPeriod++;
        }
        return periodList;
    }
    /**
     * 获取学校的所有年级
     *
     */
    private List<Meta> getAllgradeMetaList(PtOrg org) {
        // 学校的学段-年级map
        Map<Integer, List<Meta>> phasegradeMap = MetaUtils.getOrgTypeProvider().listPhaseXzGradeMap(org.getSchoolings());
        List<Meta> gradeMetaList = new ArrayList<Meta>();
        Collection<List<Meta>> gradeListList = phasegradeMap.values();
        for (List<Meta> gradeListTemp : gradeListList) {
            gradeMetaList.addAll(gradeListTemp);
        }
        return gradeMetaList;
    }
    /**
     * 获取学校的所有的教师map
     *
     */
    private Map<String, String> getTeacherMap(String orgId) {
        PtUserRole ru = new PtUserRole();
        ru.setOrgId(orgId);
        List<PtUserRole> teacherList = ptUserRoleService.listTeacherByOrg_Phase_Subject(ru);
        Map<String, String> teacherMap = new HashMap<String, String>();
        for (PtUserRole ur : teacherList) {
            teacherMap.put(ur.getName(), ur.getAccountId());
        }
        return teacherMap;
    }

    /**
     * 获取年级名称——学段Map
     *
     */
    private Map<String, Integer> getGradePhaseMap(PtOrg org) {
        // 学校的学段-年级map
        Map<Integer, List<Meta>> phasegradeMap = MetaUtils.getOrgTypeProvider().listPhaseXzGradeMap(org.getSchoolings());
        Map<String, Integer> gradePhaseMap = new HashMap<String, Integer>();
        for (Integer phaseId : phasegradeMap.keySet()) {
            for (Meta m : phasegradeMap.get(phaseId)) {
                gradePhaseMap.put(m.getName(), phaseId);
            }
        }
        return gradePhaseMap;
    }
    @Override
    public StringBuilder batchImportClass(String orgId, MultipartFile file, Integer schoolYear) {
        Map<String, Object> params = new HashMap<String, Object>();
        StringBuilder resultStr = new StringBuilder(); // 反馈信息
        params.put("orgId", orgId);
        params.put("schoolYear", schoolYear);
        try {
            ClassInfoMessage classInfoVo = new ClassInfoMessage();
            classInfoVo.setOrgId(orgId);
            classInfoVo.setStartTime(new Date());
            resultStr.append("<strong>==》开始导入数据</strong><br>");
            this.importData(file.getInputStream(), ExcelType.parseExcelType(file.getOriginalFilename()), params, resultStr);
            resultStr.append("<br><strong>《==数据导入结束。</strong>");
            List<PtClass> batchInsertClassList = (List<PtClass>) params.get("batchInsertClassList");
            List<PtClass> batchUpdateClassList = (List<PtClass>) params.get("batchUpdateClassList");
            if (batchInsertClassList.size() > 0) {
                classService.insertBatch(batchInsertClassList);
                try {
                    classInfoVo.setEndTime(new Date());
                    classInfoVo.setMessageType(MessageTypes.CLASS_BATCH_INSERT.name());
                    classInfoVo.setSchoolYear(schoolYear);
                    jmsService.sendMessage(classInfoVo);
                } catch (Exception e) {
                    logger.error("组织机构管理——班级管理——批量导入班级——消息发送失败", e);
                }
            }
            if (batchUpdateClassList.size() > 0) {
                for (PtClass c : batchUpdateClassList) {
                    classService.updateById(c);
                }
                try {
                    classInfoVo.setEndTime(new Date());
                    classInfoVo.setMessageType(MessageTypes.CLASS_BATCH_UPDATE.name());
                    classInfoVo.setSchoolYear(schoolYear);
                    jmsService.sendMessage(classInfoVo);
                } catch (Exception e) {
                    logger.error("组织机构管理——班级管理——批量导入班级——消息发送失败", e);
                }
            }
           // LoggerUtils.insertLogger(LoggerModule.ORGMANAGE, "组织机构管理——班级管理——批量导入班级，学校ID:{}", orgId);

        } catch (Exception e) {
            resultStr.append("批量导入失败：").append(e.getMessage());
            logger.error("read excel file failed", e);
        }

        return resultStr;
    }
    @Override
    protected void beforeSheetParse(Sheet sheet, Map<String, Object> params, StringBuilder returnMsg) {
        PtAccount account = ShiroKit.getSessionAttr(SessionKey.CURRENT_USER);// 当前登录账号
        params.put("userId", account.getId());
        String orgId = String.valueOf(params.get("orgId"));
        PtOrg org = orgMapper.selectById(orgId);
        // 年级班级匹配
        List<Meta> gradeMetaList = getAllgradeMetaList(org);
        Map<String, PtClass> allClassMap = new HashMap<String, PtClass>();
        Map<String, Integer> gradeMetaMap = new HashMap<String, Integer>();
        for (Meta gradeMeta : gradeMetaList) {
            gradeMetaMap.put(gradeMeta.getName(), gradeMeta.getId());
        }
        EntityWrapper<PtClass> ci = new EntityWrapper<>();
        ci.eq("org_id",orgId);
        ci.eq("enable",1);
        List<PtClass> classList = classService.selectList(ci);
        for (PtClass classInfo : classList) {
            allClassMap.put(classInfo.getName(), classInfo);
        }
        List<String> periodList = createPeriodList();// 级届集合
        params.put("periodList", periodList);
        params.put("gradeMetaMap", gradeMetaMap);
        params.put("allClassMap", allClassMap);
        Map<String, Integer> gradePhaseMap = getGradePhaseMap(org);
        params.put("gradePhaseMap", gradePhaseMap);
        Map<String, Integer> checkRepeatClassMap = new HashMap<String, Integer>(); // 检查待导入的班级是否有重复的
        params.put("checkRepeatClassMap", checkRepeatClassMap);
        List<PtClass> batchInsertClassList = new ArrayList<PtClass>();
        params.put("batchInsertClassList", batchInsertClassList);
        List<PtClass> batchUpdateClassList = new ArrayList<PtClass>();
        params.put("batchUpdateClassList", batchUpdateClassList);
        params.put("orgName", org.getName());
        Map<ExcelTitle, Column> headers = parseExcelHeader(sheet, params);
        if (headers.get(ExcelHeader.TEACHER) != null) { // 需要导入班主任
            Map<String, String> teacherMap = getTeacherMap(orgId);
            params.put("teacherMap", teacherMap);
        }
        if (headers.get(ExcelHeader.CLASSTYPE) != null) { // 需要导入班级类型
            Map<String, Integer> classTypeMap = getMetaMap("class_type");
            params.put("classTypeMap", classTypeMap);
        }
        if (headers.get(ExcelHeader.SUBJECTTYPE) != null) { // 需要导入文理科
            Map<String, Integer> subjectTypeMap = getMetaMap("department_system");
            params.put("subjectTypeMap", subjectTypeMap);
        }
    }
    @Override
    protected void parseRow(Map<ExcelTitle, String> rowValueMap, Map<String, Object> params, Row row, StringBuilder sb) {
        if (row != null) {
            int i = row.getRowNum() + 1;
            Map<String, Integer> gradeMetaMap = (Map<String, Integer>) params.get("gradeMetaMap");
            Map<String, Integer> gradePhaseMap = (Map<String, Integer>) params.get("gradePhaseMap");
            List<PtClass> batchInsertClassList = (List<PtClass>) params.get("batchInsertClassList");
            List<PtClass> batchUpdateClassList = (List<PtClass>) params.get("batchUpdateClassList");
            Map<String, String> teacherMap = (Map<String, String>) params.get("teacherMap");
            Map<String, Integer> classTypeMap = (Map<String, Integer>) params.get("classTypeMap");
            Map<String, Integer> subjectTypeMap = (Map<String, Integer>) params.get("subjectTypeMap");
            String className = rowValueMap.get(ExcelHeader.CLASSNAME);
            String period = rowValueMap.get(ExcelHeader.PERIOD);
            String gradeName = rowValueMap.get(ExcelHeader.GRADE);
            String teacherName = rowValueMap.get(ExcelHeader.TEACHER);
            String classType = rowValueMap.get(ExcelHeader.CLASSTYPE);
            String subjectType = rowValueMap.get(ExcelHeader.SUBJECTTYPE);
            String orgId = String.valueOf(params.get("orgId"));
            String userId = String.valueOf(params.get("userId"));
            Integer schoolYear = (Integer) params.get("schoolYear");
            // 数据校验
            if (!checkCulumn(i, rowValueMap, sb, params)) {
                return;
            }
            Map<String, Integer> checkRepeatClassMap = (Map<String, Integer>) params.get("checkRepeatClassMap");
            if (checkRepeatClassMap.get(className) != null) {
                sb.append("第").append(i).append("行班级名称与第").append(checkRepeatClassMap.get(className)).append("行重复，已忽略此行数据。<br>");
                logger.debug("第{}行班级名称与第" + checkRepeatClassMap.get(className) + "行重复，已忽略此行数据。", i);
                return;
            } else {
                PtClass tempClass = new PtClass();
                tempClass.setName(className);
                tempClass.setOrgId(orgId);
                tempClass.setEnable(true);
                tempClass = classMapper.selectOne(tempClass);
                PtClass classInfo = new PtClass();
                classInfo.setName(className);
                classInfo.setPeriod(Integer.valueOf(period));
                if (StringUtils.isNotBlank(gradeName)) {
                    classInfo.setGradeId(gradeMetaMap.get(gradeName));
                }
                classInfo.setOrgId(orgId);
                classInfo.setOrgName(String.valueOf(params.get("orgName")));
                classInfo.setPhaseId(gradePhaseMap.get(gradeName));
                classInfo.setEnable(true);
                if (teacherMap != null && StringUtils.isNotBlank(teacherName)) {
                    classInfo.setTeacherId(teacherMap.get(teacherName));
                    classInfo.setTeacherName(teacherName);
                }
                if (classTypeMap != null && StringUtils.isNotBlank(classType)) {
                    classInfo.setClassType(classTypeMap.get(classType));
                }else {
                    classInfo.setClassType(50);
                }
                if (subjectTypeMap != null && StringUtils.isNotBlank(subjectType)) {
                    classInfo.setSubjectType(subjectTypeMap.get(subjectType));
                }
                if (tempClass == null) {
                    classInfo.setSort(0);
                    classInfo.setCrtId(userId);
                    classInfo.setCrtDttm(new Date());
                    classInfo.setSchoolYear(schoolYear);
                    classInfo.setGraduationStatus(PtClass.not_graduation);
                    classInfo.setStatus(PtClass.update_not_begin);
                    batchInsertClassList.add(classInfo);
                } else {
                    classInfo.setId(tempClass.getId());
                    if (hasChange(classInfo, tempClass)) {
                        classInfo.setSort(0);
                        classInfo.setLastupId(userId);
                        classInfo.setLastupDttm(new Date());

                        batchUpdateClassList.add(classInfo);
                    }
                }
                checkRepeatClassMap.put(className, i);
            }
        }
    }

    private boolean hasChange(PtClass classInfo, PtClass tempClass) {
        String[] ignoreArr={"id"};
        Boolean flag = Reflections.compareFields(classInfo, tempClass, ignoreArr);
        return flag;
    }

    private boolean checkCulumn(int i, Map<ExcelTitle, String> rowValueMap, StringBuilder sb, Map<String, Object> params) {
        List<String> periodList = (List<String>) params.get("periodList");
        Map<String, Integer> gradeMetaMap = (Map<String, Integer>) params.get("gradeMetaMap");
        // Map<String,ClassInfo> allClassMap =
        // (Map<String,ClassInfo>)params.get("allClassMap");
        // 校验空数据
        String gradeName = rowValueMap.get(ExcelHeader.GRADE);
        String period = rowValueMap.get(ExcelHeader.PERIOD);
        String className = rowValueMap.get(ExcelHeader.CLASSNAME);
        String teacherName = rowValueMap.get(ExcelHeader.TEACHER);
        String classType = rowValueMap.get(ExcelHeader.CLASSTYPE);

        if (StringUtils.isEmpty(period) || StringUtils.isEmpty(gradeName) || StringUtils.isEmpty(className)) {
            sb.append("第" + (i) + "行必填项有空值，已忽略此行数据。<br>");
            logger.debug("第{}行必填项有空值，忽略此行数据。", i);
            return false;
        }
        if (!periodList.contains(period)) {
            sb.append("第" + (i) + "行：级届超出规定范围，已忽略此行数据。<br>");
            logger.debug("第" + (i) + "行：级届超出规定范围，已忽略此行数据", i);
            return false;
        }
        if (StringUtils.isNotBlank(gradeName) && gradeMetaMap.get(gradeName) == null) {
            sb.append("第" + (i) + "行：年级不存在，已忽略此行数据。<br>");
            logger.debug("第" + (i) + "行：年级不存在，已忽略此行数据", i);
            return false;
        }
        // if(allClassMap.get(className) != null){
        // sb.append("第" + (i) + "行：班级名称已经存在，不可重复！已忽略此行数据。<br>");
        // logger.debug("第" + (i) + "行：班级名称已经存在，不可重复！已忽略此行数据", i);
        // return false;
        // }
        Map<String, String> teacherMap = (Map<String, String>) params.get("teacherMap");
        if (teacherMap != null) {
            if (StringUtils.isNotBlank(teacherName) && teacherMap.get(teacherName) == null) {
                sb.append("第" + (i) + "行：班主任不存在，已忽略此行数据。<br>");
                logger.debug("第" + (i) + "行：班主任不存在，已忽略此行数据", i);
                return false;
            }
        }
        Map<String, Integer> classTypeMap = (Map<String, Integer>) params.get("classTypeMap");
        if (classTypeMap != null) {
            if (StringUtils.isNotBlank(classType) && classTypeMap.get(classType) == null) {
                sb.append("第" + (i) + "行：班级类型不存在，已忽略此行数据。<br>");
                logger.debug("第" + (i) + "行：班级类型不存在，已忽略此行数据", i);
                return false;
            }
        }
        String subjectType = rowValueMap.get(ExcelHeader.SUBJECTTYPE);
        Map<String, Integer> subjectTypeMap = (Map<String, Integer>) params.get("subjectTypeMap");
        if (subjectTypeMap != null && subjectTypeMap.get(subjectType) == null) {
            sb.append("第" + (i) + "行：文理科不存在，已忽略此行数据。<br>");
            logger.debug("第" + (i) + "行：文理科不存在，已忽略此行数据", i);
            return false;
        }
        return true;
    }
//    /**
//     * 比较新旧班级信息
//     *
//     */
//    private Boolean hasChange(PtClass newClass, PtClass oldClass) {
//        boolean hasChange = false;
//        // 遍历属性
//        Class<?> c = newClass.getClass();
//        Table t = MapperContainer.getTable(c.getSimpleName());
//        for (Method method : c.getMethods()) {
//            if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
//                try {
//                    String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
//                    if (t.getColumnByAttrName(property) != null && !"crtDttm".equals(property) && !"crtId".equals(property) && !"lastupDttm".equals(property)
//                            && !"lastupId".equals(property) && !property.equalsIgnoreCase(t.getPkName())) { // 不比较主键
//                        Object value = method.invoke(newClass);
//                        Object oldValue = method.invoke(oldClass);
//                        if (canContinue(value, oldValue)) {
//                            continue;
//                        } else if (value != null) {
//                            hasChange = true;
//                        }
//                        Reflections.invokeSetter(oldClass, property, value);
//                    }
//                } catch (Exception e) {
//                    logger.error("fail to inject via method " + method.getName() + " of interface ");
//                }
//            }
//        }
//        return hasChange;
//    }

    private boolean canContinue(Object value, Object oldValue) {
        return (value == null && oldValue == null) || (value != null && value.equals(oldValue));
    }
    @Override
    protected ExcelTitle[] titles() {
        return ExcelHeader.values();
    }

    @Override
    public int sheetIndex() {
        return 0;
    }

    @Override
    public int titleLine() {
        return headline;
    }
    @Override
    protected String prepareTitle(String name) {
        name = super.prepareTitle(name);
        return name != null && name.length() > 4 ? name.replaceAll("\\(必填\\)", "") : name;
    }
    /**
     * 判定模板是否设置标题列为必填
     *
     */
    @Override
    protected boolean isRequiredColumn(String columnName) {
        if (columnName != null) {
            return columnName.contains("必填");
        }
        return super.isRequiredColumn(columnName);
    }


}
